﻿
using Autofac;
using Autofac.Extras.DynamicProxy;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.OpenApi.Models;
using My.Application;
using My.Application.Orders;
using My.EntityFrameworkCore;
using My.HttpApi;
using My.WebApi.Localization;
using System.Reflection;
using Volo.Abp;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Auditing;
using Volo.Abp.Autofac;
using Volo.Abp.DynamicProxy;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.EventBus.RabbitMq;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;
using Volo.Abp.Uow;
using Volo.Abp.VirtualFileSystem;

namespace My.WebApi
{
    [DependsOn(
        typeof(AbpAutofacModule),
        typeof(HttpApiModule),
        typeof(ApplicationModule),
        typeof(EntityFrameworkCoreModule),
        typeof(AbpSwashbuckleModule),
        typeof(AbpEventBusRabbitMqModule),
        typeof(AbpLocalizationModule)
        )]
    public class WebApiModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var configuration = context.Services.GetConfiguration();
            //var a1 = configuration["IdentityUserLockoutOptions:MaxUserLoginErrorCount"];
            //var a = int.Parse(a1);
            //var b = int.Parse(configuration["IdentityUserLockoutOptions:UserLockoutMinutes"]);
            var hostingEnvironment = context.Services.GetHostingEnvironment();
            ConfigureSwaggerServices(context, configuration);

            Configure<AbpAuditingOptions>(options =>
            {
                options.IsEnabled = true;
                options.IsEnabledForGetRequests = true;
                options.IsEnabledForAnonymousUsers = true;
                options.ApplicationName = "MyWebApi";
            });

            context.Services.AddAuthentication("Bearer").AddIdentityServerAuthentication(options =>
            {
                options.Authority = configuration["AuthServer:Authority"];
                options.ApiName = configuration["AuthServer:ApiName"];
                options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);
            });

            Configure<AbpAspNetCoreMvcOptions>(options =>
            {
                options.ConventionalControllers.Create(typeof(My.Application.ApplicationModule).Assembly);
            });

            ConfigureCors(context, configuration);

            var containerBuilder = new ContainerBuilder();

            containerBuilder.RegisterType<Application.Orders.TestInterface>()
       .As<Application.Orders.ITestInterface>()
       .EnableInterfaceInterceptors().InterceptedBy(typeof(MInterceptor));
            containerBuilder.Register(c => new MInterceptor());
            var container = containerBuilder.Build();
            context.Services.AddTransient(x =>
            {
                return container.Resolve<Application.Orders.ITestInterface>();
            });

            Configure<MvcOptions>(options =>
            {
                //options.Filters.Add<Filters.GlobalExceptionFilter>();
                options.Filters.Add<Filters.UserLoginStatusFilter>();
            });

            Configure<AbpVirtualFileSystemOptions>(options =>
            {
                options.FileSets.AddEmbedded<WebApiModule>("My.WebApi");
            });

            Configure<AbpLocalizationOptions>(options =>
            {
                options.Resources.Add<TestResource>("es").AddVirtualJson("/Localization/Resources");
                options.DefaultResourceType = typeof(TestResource);
            });

            context.Services.OnRegistred(registration =>
            {
                if (ShouldIntercept(registration.ImplementationType))
                {
                    registration.Interceptors.Add<MInterceptor>();
                }
            });

            //Configure<AbpDistributedEventBusOptions>(options =>
            //{
            //    options.Outboxes.Configure(config =>
            //    {

            //    });
            //});
        }

        private static bool ShouldIntercept(Type type)
        {
            return !DynamicProxyIgnoreTypes.Contains(type) && UnitOfWorkHelper.IsUnitOfWorkType(type.GetTypeInfo());
        }

        private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddCors(options =>
            {
                options.AddDefaultPolicy(builder =>
                {
                    builder
                        .WithOrigins(
                            configuration["App:CorsOrigins"]
                                .Split(",", StringSplitOptions.RemoveEmptyEntries)
                                .Select(o => o.RemovePostFix("/"))
                                .ToArray()
                        )
                        .WithAbpExposedHeaders()
                        .SetIsOriginAllowedToAllowWildcardSubdomains()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                });
            });
        }


        private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddAbpSwaggerGenWithOAuth(
            configuration["AuthServer:Authority"],
            new Dictionary<string, string>
            {
                    {"App", "App API"}
            },
            options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo { Title = "App API", Version = "v1" });
                options.DocInclusionPredicate((docName, description) => true);
                options.CustomSchemaIds(type => type.FullName);
            });
        }

        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseStaticFiles();
            app.UseRouting();
            app.UseCors();
            app.UseAuthentication();
            app.UseAbpClaimsMap();
            app.UseAuthorization();

            app.UseSwagger();
            app.UseAbpSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "App API");

                var configuration = context.GetConfiguration();
                options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
                options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]);
                options.OAuthScopes("App");
            });

            app.UseAuditing();//使用审计日志
            app.UseUnitOfWork();
            //app.UseMiddleware<Middlewares.UserLoginStatusMiddleware>();
            app.UseMiddleware<AbpExceptionHandlingMiddleware>();
            app.UseConfiguredEndpoints();
        }
    }
}
